package com.szt.sy.controller.system.role;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.szt.sy.anontation.Authority;
import com.szt.sy.anontation.AuthorityConfig;
import com.szt.sy.anontation.SysLog;
import com.szt.sy.common.AuthorityCommon;
import com.szt.sy.controller.base.AdminBaseController;
import com.szt.sy.entity.system.Button;
import com.szt.sy.entity.system.Menu;
import com.szt.sy.entity.system.Role;
import com.szt.sy.entity.system.RoleButton;
import com.szt.sy.entity.system.User;
import com.szt.sy.service.system.button.ButtonService;
import com.szt.sy.service.system.menu.MenuService;
import com.szt.sy.service.system.role.RoleService;
import com.szt.sy.service.system.rolebutton.RoleButtonService;
import com.szt.sy.service.system.rolemenu.RoleMenuService;
import com.szt.sy.service.system.user.UserService;
import com.szt.sy.util.json.JsonUtils;
import com.szt.sy.vo.rep.base.RepBaseVO;
import com.szt.sy.vo.rep.rolebutton.TreeNode;

/***
 * 角色控制器
 * 
 * @author wwy
 *
 */
@Controller
@AuthorityConfig(prefix = "/admin/role")
@RequestMapping(value = "admin/role")
public class RoleController extends AdminBaseController {
	
	/***
	 * 菜单地址(权限用)
	 */
	final String menuUrl = "/admin/role";
	@Autowired
	private MenuService menuService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private UserService userService;
	
	@Autowired
	private ButtonService buttonService;
	
	@Autowired
	private RoleButtonService roleButtonService;
	
	@Autowired
	private RoleMenuService roleMenuService;
	
	/**
	 * 进入权限首页
	 *
	 * @param
	 * @return
	 * @throws Exception
	 */
	@Authority(name = AuthorityCommon.LIST)
	@RequestMapping
	public ModelAndView list(String id) throws Exception {
		ModelAndView mv = this.getModelAndView();
		if (StringUtils.isBlank(id)) {
			id = "1";
		}
		// 所有顶层的角色
		List<Role> topRoleList = roleService.listAllRolesByPId("0");
		// 列出此组下架角色
		List<Role> subRoleList = roleService.listAllRolesByPId(id);
		// 取得点击的角色组(横排的)
		Role role = roleService.findObjectById(id);
		List<Button> buttons = buttonService.selectList(new EntityWrapper<>());
		mv.addObject("role", role);
		mv.addObject("buttons", buttons);
		mv.addObject("topRoleList", topRoleList);
		mv.addObject("subRoleList", subRoleList);
		
		mv.setViewName("system/role/role_list");
		
		return mv;
	}
	
	/**
	 * 去新增页面
	 *
	 * @param
	 * @return
	 */
	@Authority(name = AuthorityCommon.ADD)
	@RequestMapping(value = "/toAdd")
	public ModelAndView toAdd(String parentId) {
		ModelAndView mv = this.getModelAndView();
		Role role = new Role();
		role.setParentId(parentId);
		mv.addObject("msg", "add");
		mv.setViewName("system/role/role_edit");
		mv.addObject("entity", role);
		return mv;
	}
	
	/**
	 * 保存新增角色
	 *
	 * @return
	 * @throws Exception
	 */
	@SysLog("角色-添加")
	@Authority(name = AuthorityCommon.ADD)
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public ModelAndView add(Role role) throws Exception {
		ModelAndView mv = this.getModelAndView();
		role.setDelAble(Role.DelAble.YES);
		if (Role.ROLE_ROOT_ID.equals(role.getParentId())) {
			role.setRights(Role.EMPTY_RIGHTS);
		} else {
			String rights = roleService.findObjectById(role.getParentId()).getRights();
			// 组菜单权限
			role.setRights(StringUtils.defaultString(rights));
		}
		role.setAdds(Role.EMPTY_RIGHT);
		role.setEdits(Role.EMPTY_RIGHT);
		role.setDels(Role.EMPTY_RIGHT);
		role.setQuerys(Role.EMPTY_RIGHT);
		roleService.add(role);
		mv.setViewName("save_result");
		return mv;
	}
	
	/**
	 * 请求编辑
	 *
	 * @param ROLE_ID
	 * @return
	 * @throws Exception
	 */
	@Authority(name = AuthorityCommon.EDIT)
	@RequestMapping(value = "/toEdit")
	public ModelAndView toEdit(String id) throws Exception {
		ModelAndView mv = this.getModelAndView();
		Role role = roleService.findObjectById(id);
		mv.addObject("msg", "edit");
		mv.addObject("entity", role);
		mv.setViewName("system/role/role_edit");
		return mv;
	}
	
	/**
	 * 保存修改
	 *
	 * @return
	 * @throws Exception
	 */
	@SysLog("角色-修改")
	@Authority(name = AuthorityCommon.EDIT)
	@RequestMapping(value = "/edit")
	public ModelAndView edit(Role role) throws Exception {
		ModelAndView mv = this.getModelAndView();
		roleService.edit(role);
		mv.addObject("msg", "success");
		mv.setViewName("save_result");
		return mv;
	}
	
	/**
	 * 删除角色
	 *
	 * @param ROLE_ID
	 * @return
	 * @throws Exception
	 */
	@SysLog("角色-删除")
	@Authority(name = AuthorityCommon.DELETE)
	@RequestMapping(value = "/delete")
	@ResponseBody
	public RepBaseVO deleteRole(@RequestParam String id) throws Exception {
		RepBaseVO repVO = new RepBaseVO<>();
		// 列出此部门的所有下级
		List<Role> subRoles = roleService.listAllRolesByPId(id);
		if (subRoles.size() > 0) {
			// 下级有数据时，删除失败
			return repVO.setCommonFail().setMes("含有下级角色，请先删除下级角色");
		}
		// 此角色下的用户
		List<User> userlist = userService.listAllUserByRoldId(id);
		// 此角色已被使用就不能删除
		if (userlist.size() > 0) {
			return repVO.setCommonFail().setMes("角色含有用户，请先删除用户");
		}
		// 执行删除
		roleService.deleteRoleById(id);
		return repVO.setCommonSuccess();
	}
	
	/**
	 * 显示菜单列表ztree(菜单授权菜单)
	 *
	 * @param model
	 * @return
	 */
	@Authority(name = AuthorityCommon.LIST)
	@RequestMapping(value = "/menuqx")
	public String listAllMenu(Model model, String id) throws Exception {
		// 根据角色ID获取角色对象
		Role role = roleService.getRoleById(id);
		// 取出本角色菜单权限
		String roleRights = role.getRights();
		// 获取所有菜单
		List<Menu> menuList = menuService.getAllMenuAuthorityByRole(id);
		String json = JsonUtils.beanToString(menuList);
		json = json.replaceAll("id", "id").replaceAll("parentId", "pId").replaceAll("menuName", "name")
				.replaceAll("subMenu", "nodes").replaceAll("ownMenuRights", "checked");
		model.addAttribute("zTreeNodes", json);
		model.addAttribute("id", id);
		return "system/role/menuqx";
	}
	
	/**
	 * 保存角色菜单权限
	 *
	 * @param ROLE_ID
	 *            角色ID
	 * @param menuIds
	 *            菜单ID集合
	 * @param out
	 * @throws Exception
	 */
	@SysLog("角色-保存角色菜单权限")
	@Authority(name = AuthorityCommon.EDIT)
	@RequestMapping(value = "/saveMenuqx")
	@ResponseBody
	public RepBaseVO saveMenuqx(@RequestParam String roleId, @RequestParam(value = "menuIds[]") List<String> menuIds)
			throws Exception {
		roleMenuService.updateRoleMenus(roleId, menuIds);
		return RepBaseVO.newIntance().setCommonSuccess();
		
	}
	
	/**
	 * 请求角色按钮授权页面(增删改查)
	 *
	 * @param ROLE_ID：
	 *            角色ID
	 * @param msg：
	 *            区分增删改查
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/button/auth/edit")
	public String buttonAuthEditPage(String roleId, String buttonId, Model model) throws Exception {
		// 先获取所有顶层菜单，递归获取所有菜单
		List<Menu> menuList = menuService.listAllMenu(Menu.ROOT_ID);
		List<RoleButton> roleButtons = roleButtonService
				.selectList(new EntityWrapper<RoleButton>().eq("roleId", roleId).eq("buttonId", buttonId));
		List<TreeNode> treeNodeList = getTreeNodes(menuList, buttonId, roleId, roleButtons);
		String json = JsonUtils.beanToString(treeNodeList);
		System.out.println(json);
		model.addAttribute("zTreeNodes", json);
		model.addAttribute("roleId", roleId);
		model.addAttribute("buttonId", buttonId);
		return "system/role/b4Button";
	}
	
	@PostMapping("/button/auth/edit")
	@ResponseBody
	public RepBaseVO buttonAuthEdit(String roleId, String buttonId,
			@RequestParam(value = "menuIds[]") List<String> menuIds) {
		RepBaseVO repVO = new RepBaseVO();
		roleButtonService.updateRoleButtons(roleId, buttonId, menuIds);
		return repVO.setCommonSuccess();
	}
	
	private List<TreeNode> getTreeNodes(List<Menu> menuList, String buttonId, String roleId,
			List<RoleButton> roleButtonList) {
		List<TreeNode> treeNodeList = new ArrayList<>(menuList.size());
		for (Menu menu : menuList) {
			boolean checked = roleButtonList.parallelStream().filter((roleButton) -> {
				if (roleButton.getMenuId().equals(menu.getId())) {
					return true;
				}
				return false;
			}).count() > 0;
			TreeNode treeNode = new TreeNode();
			
			treeNode.setMenuId(menu.getId() + "");
			treeNode.setChecked(checked);
			treeNode.setName(menu.getMenuName());
			if (menu.getSubMenu() != null && menu.getSubMenu().size() > 0) {
				treeNode.setNodes(getTreeNodes(menu.getSubMenu(), buttonId, roleId, roleButtonList));
			}
			treeNodeList.add(treeNode);
		}
		return treeNodeList;
	}
	
	/**
	 * 根据角色权限处理权限状态(递归处理)
	 *
	 * @param menuList：传入的总菜单
	 * @param roleRights：加密的权限字符串
	 * @return
	 */
	private List<Menu> readMenu(List<Menu> menuList, String roleRights) {
		for (int i = 0; i < menuList.size(); i++) {
			menuList.get(i).setOwnMenuRights(true);
			// 继续排查其子菜单
			this.readMenu(menuList.get(i).getSubMenu(), roleRights);
		}
		return menuList;
	}
	
}